package com.lykj.lib_base.app

import android.app.Activity
import android.app.ActivityManager
import android.app.Application
import android.content.Context
import android.graphics.Typeface
import android.os.Process
import android.text.TextUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.SPUtils
import com.lykj.lib_base.data.bean.response.AgentLoginResponse
import com.lykj.lib_base.data.bean.response.LoginResponse
import com.lykj.lib_base.net.http.RetrofitManager
import com.tencent.mmkv.MMKV
import me.jessyan.autosize.AutoSize
import me.jessyan.autosize.AutoSizeConfig
import me.jessyan.autosize.onAdaptListener
import me.jessyan.autosize.utils.AutoSizeLog
import me.jessyan.autosize.utils.ScreenUtils
import okhttp3.WebSocket
import java.lang.String
import java.lang.reflect.Field
import java.util.Locale

/**
 * ================================================
 * 基础的Application
 * ================================================
 * @date 2022/9/2-11:23
 * @author gosha
 */
open class BaseApplication : Application() {
    private lateinit var typeface: Typeface
    private var mUserInfo: LoginResponse.DataDTO? = null
    private var mAgentUserInfo: AgentLoginResponse.DataDTO? = null
    private var mWebSocket: WebSocket? = null
    private val TAG = "BaseApplication"

    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        instance = this
    }

    override fun onCreate() {
        super.onCreate()
        val processName = getProcessName(this)
        if (processName != null) {
            if (processName == "com.lykj.llw.box") {
//                preinitX5WebCore()
//                setGlobalCustomFont()
                MMKV.initialize(this)

                initAutoSize()
                RetrofitManager.instance.init()
//                initJPushShare()
                //捕获异常,不cash
//                HookLooper.hook()
            }
        }
    }

    open fun getProcessName(context: Context): kotlin.String? {
        val am = context.getSystemService(ACTIVITY_SERVICE) as ActivityManager
        val runningApps = am.runningAppProcesses ?: return null
        for (proInfo in runningApps) {
            if (proInfo.pid == Process.myPid()) {
                if (proInfo.processName != null) {
                    return proInfo.processName
                }
            }
        }
        return null
    }

    private fun initJPushShare() {
//        JShareInterface.setDebugMode(true)
//        val platformConfig = PlatformConfig()
//            .setWechat("wxd5f396e1b273d83a", "559dee988da345c1a378aa86889f846d")
//            .setQQ("1112169242", "NfkaqlH1injXY8V8")
//        /**
//         * since 1.5.0，1.5.0版本后增加API，支持在代码中设置第三方appKey等信息，当PlatformConfig为null时，或者使用JShareInterface.init(Context)时需要配置assets目录下的JGShareSDK.xml
//         **/
//        JShareInterface.init(this, platformConfig)
    }

    private fun setGlobalCustomFont() {
        typeface = Typeface.createFromAsset(assets, "fonts/ysbth.ttf")
        try {
            val field: Field = Typeface::class.java.getDeclaredField("MONOSPACE")
            field.isAccessible = true
            field.set(null, typeface)
        } catch (e: NoSuchFieldException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        }
    }

    private fun initAutoSize() {
        //当 App 中出现多进程, 并且您需要适配所有的进程, 就需要在 App 初始化时调用 initCompatMultiProcess()
        AutoSize.initCompatMultiProcess(this)

        /**
         * 以下是 AndroidAutoSize 可以自定义的参数, {@link AutoSizeConfig} 的每个方法的注释都写的很详细
         * 使用前请一定记得跳进源码，查看方法的注释, 下面的注释只是简单描述!!!
         */

        //如果在某些特殊情况下出现 InitProvider 未能正常实例化, 导致 AndroidAutoSize 未能完成初始化
        //可以主动调用 AutoSize.checkAndInit(this) 方法, 完成 AndroidAutoSize 的初始化后即可正常使用
//        AutoSize.checkAndInit(this);

//        如何控制 AndroidAutoSize 的初始化，让 AndroidAutoSize 在某些设备上不自动启动？https://github.com/JessYanCoding/AndroidAutoSize/issues/249
        /**
         * 以下是 AndroidAutoSize 可以自定义的参数, [AutoSizeConfig] 的每个方法的注释都写的很详细
         * 使用前请一定记得跳进源码，查看方法的注释, 下面的注释只是简单描述!!!
         */
        AutoSizeConfig.getInstance() //是否让框架支持自定义 Fragment 的适配参数, 由于这个需求是比较少见的, 所以须要使用者手动开启
            .apply {
                //如果没有这个需求建议不开启
                setCustomFragment(true).onAdaptListener = object : onAdaptListener {
                    override fun onAdaptBefore(target: Any, activity: Activity) {
                        //使用以下代码, 可以解决横竖屏切换时的屏幕适配问题
                        //使用以下代码, 可支持 Android 的分屏或缩放模式, 但前提是在分屏或缩放模式下当用户改变您 App 的窗口大小时
                        //系统会重绘当前的页面, 经测试在某些机型, 某些情况下系统不会重绘当前页面, ScreenUtils.getScreenSize(activity) 的参数一定要不要传 Application!!!
                        AutoSizeConfig.getInstance().screenWidth =
                            ScreenUtils.getScreenSize(activity)[0]
                        AutoSizeConfig.getInstance().screenHeight =
                            ScreenUtils.getScreenSize(activity)[1]
                        AutoSizeLog.d(
                            String.format(
                                Locale.ENGLISH,
                                "%s onAdaptBefore!",
                                target.javaClass.name
                            )
                        )
                    }

                    override fun onAdaptAfter(target: Any, activity: Activity) {
                        AutoSizeLog.d(
                            String.format(
                                Locale.ENGLISH,
                                "%s onAdaptAfter!",
                                target.javaClass.name
                            )
                        )
                    }
                }
                //是否打印 AutoSize 的内部日志, 默认为 true, 如果您不想 AutoSize 打印日志, 则请设置为 false
                setLog(false)
                //是否使用设备的实际尺寸做适配, 默认为 false, 如果设置为 false, 在以屏幕高度为基准进行适配时
                //AutoSize 会将屏幕总高度减去状态栏高度来做适配
                //设置为 true 则使用设备的实际屏幕高度, 不会减去状态栏高度
                //在全面屏或刘海屏幕设备中, 获取到的屏幕高度可能不包含状态栏高度, 所以在全面屏设备中不需要减去状态栏高度，所以可以 setUseDeviceSize(true)
                isUseDeviceSize = true
                //是否全局按照宽度进行等比例适配, 默认为 true, 如果设置为 false, AutoSize 会全局按照高度进行适配
                designWidthInDp = 360
                isBaseOnWidth = true
                //设置屏幕适配逻辑策略类, 一般不用设置, 使用框架默认的就好
//                setAutoAdaptStrategy(object :AutoAdaptStrategy{
//                    override fun applyAdapt(target: Any?, activity: Activity?) {
//                    }
//                })
            }
    }


    /**
     * 获取用户信息
     */
    open fun getUserInfo(): LoginResponse.DataDTO? {
        if (null == mUserInfo) {
            //FIXME:测试用
            val jsonStr = SPUtils.getInstance("user").getString("userInfo", "")
            mUserInfo = if (TextUtils.isEmpty(jsonStr)) {
                null
            } else {
                GsonUtils.fromJson(jsonStr, LoginResponse::class.java).data
            }
        }

        return mUserInfo
    }

    /**
     * 获取代理用户信息
     */
    open fun getAgentUserInfo(): AgentLoginResponse.DataDTO? {
        if (null == mAgentUserInfo) {
            val jsonStr = SPUtils.getInstance("agent_user").getString("userInfo", "")
            mAgentUserInfo = if (TextUtils.isEmpty(jsonStr)) {
                null
            } else {
                GsonUtils.fromJson(jsonStr, AgentLoginResponse::class.java).data
            }
        }

        return mAgentUserInfo
    }

    /**
     * 登录成功后设置用户信息
     */
    fun setUserInfo(userInfo: LoginResponse) {
        mUserInfo = userInfo.data
    }

    /**
     * 登录成功后设置代理用户信息
     */
    fun setAgentUserInfo(userInfo: AgentLoginResponse) {
        mAgentUserInfo = userInfo.data
    }

    /**
     * 清除用户信息
     * @param onlyMemory 是否清除本地存储信息
     */
    fun clearUserInfo(onlyMemory: Boolean) {
        mUserInfo = null

        if (!onlyMemory) {
            SPUtils.getInstance("user").remove("userInfo")
        }
    }

    /**
     * 清除代理用户信息
     * @param onlyMemory 是否清除本地存储信息
     */
    fun clearAgentUserInfo(onlyMemory: Boolean) {
        mAgentUserInfo = null

        if (!onlyMemory) {
            SPUtils.getInstance("agent_user").remove("userInfo")
        }
    }

    fun getMWebSocket(): WebSocket? {
        return mWebSocket
    }

    fun setWebSocket(webSocket: WebSocket?) {
        mWebSocket = webSocket
    }

    companion object {
        /**
         * 获取全局唯一上下文
         *
         * @return BaseApplication
         */
        //全局唯一的context
        var instance: BaseApplication? = null
            private set
    }
}